package com.xbongbong.paas.service.log.crm.operation.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.CrmLogMemoConstant;
import com.xbongbong.paas.log.pojo.InfoArrPojo;
import com.xbongbong.paas.pojo.dto.CustomerMergeDTO;
import com.xbongbong.paas.pojo.dto.FormDataAddDTO;
import com.xbongbong.paas.pojo.dto.FormDataThoroughDeleteDTO;
import com.xbongbong.paas.pojo.dto.FormDataUpdateDTO;
import com.xbongbong.paas.service.log.crm.help.OperationLogHelp;
import com.xbongbong.paas.service.log.crm.operation.AbstractCrmOperationLogHandle;
import com.xbongbong.paas.service.log.crm.operation.CustomerOperationLogHandle;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.parent.interfaces.logger.ArchiveOperationLogHandle;
import com.xbongbong.parent.interfaces.logger.FocusOperationLogHandle;
import com.xbongbong.parent.interfaces.logger.PushNotifyLogHandle;
import com.xbongbong.pro.formdata.pojo.vo.BeforeSaveVO;
import com.xbongbong.pro.formdata.pojo.vo.BeforeUpdateVO;
import com.xbongbong.pro.formdata.pojo.vo.SaveVO;
import com.xbongbong.pro.formdata.pojo.vo.UpdateVO;
import com.xbongbong.pro.listbatch.pojo.dto.ListBatchDTO;
import com.xbongbong.pro.log.pojo.DetailLogPojo;
import com.xbongbong.pro.log.pojo.dto.AddFocusDTO;
import com.xbongbong.pro.log.pojo.dto.AddOperationLogDTO;
import com.xbongbong.pro.log.pojo.dto.BackToPublicDTO;
import com.xbongbong.pro.log.pojo.dto.CustomerGrabLogDTO;
import com.xbongbong.pro.log.pojo.dto.CustomerMergeLogDTO;
import com.xbongbong.pro.log.pojo.dto.DeleteFocusDTO;
import com.xbongbong.pro.log.pojo.dto.DeletePushNotifyDTO;
import com.xbongbong.pro.log.pojo.dto.RevertLogDTO;
import com.xbongbong.pro.log.pojo.dto.ThoroughDeleteLogDTO;
import com.xbongbong.pro.log.pojo.dto.UpdateOperationLogDTO;
import com.xbongbong.saas.domain.entity.ext.ClueEntityExt;
import com.xbongbong.saas.domain.entity.ext.CustomerEntityExt;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.RedundantTemplateTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ClueEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.enums.dictionary.PublicEnum;
import com.xbongbong.saas.model.ClueModel;
import com.xbongbong.saas.service.toolbox.help.LogHelp;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;


/**
 * @author: yingjianfeng
 * @date: 2022/4/13 16:42
 * @description: 客户操作日志
 */
@Slf4j
@Service("customerOperationLogHandleImpl")
public class CustomerOperationLogHandleImpl extends AbstractCrmOperationLogHandle
        implements CustomerOperationLogHandle, PushNotifyLogHandle,
        FocusOperationLogHandle, ArchiveOperationLogHandle {
    @Resource
    private ClueModel clueModel;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private LogHelp logHelp;


    @Override
    public List<Integer> type() {
        return Arrays.asList(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
    }

    @Override
    @Async("sysLogThreadPool")
    public void deletePushNotify(DeletePushNotifyDTO deletePushNotifyDTO) {
        deletePushNotify(deletePushNotifyDTO,CustomerManagementEnum.NAME.getAttr());
    }


    @Override
    @Async("sysLogThreadPool")
    public void add(AddOperationLogDTO addOperationLogDTO) {
        try {
            FormDataAddDTO formDataAddDTO = addOperationLogDTO.getFormDataAddDTO();
            PaasFormDataEntity newPaasFormDataEntity = addOperationLogDTO.getNewPaasFormDataEntity();
            SaveVO saveVO = addOperationLogDTO.getSaveVO();
            BeforeSaveVO beforeSaveVO = addOperationLogDTO.getBeforeSaveVO();
            String corpid = formDataAddDTO.getCorpid();
            boolean isImport = Objects.equals(1, formDataAddDTO.getIsImport());
            if (isImport) {
                return;
            }
            JSONObject data = newPaasFormDataEntity.getData();
            String logName = OperationLogHelp.getName(type(),data);
            Integer isPublic = FastJsonHelper.getIntegerOrDefaultFromFormData(data, CustomerManagementEnum.IS_PUBLIC.getAttr(), 0);
            String memoName = beforeSaveVO.getPaasFormEntityExt().getName();
            UserVO userVO = saveVO.getUserVO();
            String userName = userVO.getName();
            Long formId = formDataAddDTO.getFormId();
            String paasFormName = getPaasFormName(corpid, formId, formDataAddDTO.getBusinessType());
            String memo = null;
            if(Objects.equals(PublicEnum.PUBLIC.getCode(),isPublic)){
                memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_USER_ADD_WORK_IN_PUBLIC), userName, paasFormName, logName);
            }
            String clueIdStr = data.getString(CustomerManagementEnum.CLUE_ID.getAttr());
            if(StringUtils.isNotEmpty(clueIdStr)){
                List<Long> clueIdList = JSONArray.parseArray(clueIdStr, Long.class);
                Long clueId = clueIdList.get(0);
                ClueEntityExt clueEntityExt = clueModel.getByKey(clueId, corpid);
                JSONObject clueObj = clueEntityExt.getData();
                String clueName = FastJsonHelper.getStringOrDefaultFromFormData(clueObj, ClueEnum.COMPANY_NAME.getAttr(), "");
                String cluePaasFormName = getPaasFormName(corpid, clueEntityExt.getFormId(), XbbRefTypeEnum.CLUE.getCode());
                memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_USER_ADD_WORK_CLUE_CONVERT),
                        userName, cluePaasFormName,clueName,paasFormName, logName);
            }
            addSaveLogger(formDataAddDTO, newPaasFormDataEntity, logName, memoName, OperateModuleTypeEnum.CUSTOMER, saveVO, beforeSaveVO,paasFormName,memo);
        } catch (XbbException e) {
            log.error("com.xbongbong.paas.service.log.operation.impl.CustomerOperationLogHandleImpl.add fail", e);
        }
    }

    @Override
    @Async("sysLogThreadPool")
    public void update(UpdateOperationLogDTO updateOperationLogDTO) {
        try {
            FormDataUpdateDTO formDataUpdateDTO = updateOperationLogDTO.getFormDataUpdateDTO();
            UpdateVO updateVO = updateOperationLogDTO.getUpdateVO();
            BeforeUpdateVO beforeUpdateVO = updateOperationLogDTO.getBeforeUpdateVO();
            Integer editLable = updateOperationLogDTO.getEditLable();
            RedundantTemplateTypeEnum redundantTemplateTypeEnum = RedundantTemplateTypeEnum.CUSTOMER;
            boolean isCoverage = Objects.equals(1, formDataUpdateDTO.getIsCover());
            if (isCoverage) {
                return;
            }
            String corpid = formDataUpdateDTO.getCorpid();
            String memoName = beforeUpdateVO.getPaasFormEntityExt().getName();
            PaasFormDataEntity paasFormDataEntity = updateVO.getPaasFormDataEntity();
            JSONObject data = paasFormDataEntity.getData();
            String userName = updateVO.getUserVO().getName();
            Integer isPublic = FastJsonHelper.getIntegerOrDefaultFromFormData(data, CustomerManagementEnum.IS_PUBLIC.getAttr(), 0);
            String opObjectName = data.getString(CustomerManagementEnum.NAME.getAttr());
            String memo = "";
            if(Objects.equals(PublicEnum.PUBLIC.getCode(), isPublic)){
                if(Objects.equals(editLable, 0)){
                    memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_USER_UPDATE_WORK_IN_PUBLIC), userName, memoName, opObjectName);
                }else{
                    memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_USER_UPDATE_LABLE_WORK_IN_PUBLIC), userName, memoName, opObjectName);
                }
            }else{
                if(Objects.equals(editLable, 0)){
                    memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_USER_UPDATE_WORK),
                            userName, memoName, opObjectName);
                }else{
                    memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_USER_UPDATE_LABLE_WORK),
                            userName, memoName, opObjectName);
                }
            }
            Long clueId = formDataUpdateDTO.getClueId();
            if (clueId != null && clueId > 0) {
                // 客户来自于线索转换
                ClueEntityExt clueEntityExt = clueModel.getByKey(clueId, corpid);
                JSONObject clueObj = clueEntityExt.getData();
                String clueName = FastJsonHelper.getStringOrDefaultFromFormData(clueObj, ClueEnum.COMPANY_NAME.getAttr(), "");
                memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_USER_UPDATE_CLUE_TRANS_CUSTOMER), userName, clueName, memoName, opObjectName);
                updateSaveLogger(formDataUpdateDTO, paasFormDataEntity, redundantTemplateTypeEnum, memo, opObjectName, OperateModuleTypeEnum.CUSTOMER, updateVO, beforeUpdateVO, OperateTypeEnum.TRANSFORM, IndexTypeEnum.IDX_SAAS_CUSTOMER_SUB);
            } else {
                updateSaveLogger(formDataUpdateDTO, paasFormDataEntity, redundantTemplateTypeEnum, memo, opObjectName, OperateModuleTypeEnum.CUSTOMER, updateVO, beforeUpdateVO, OperateTypeEnum.EDIT, IndexTypeEnum.IDX_SAAS_CUSTOMER_SUB);
            }
        } catch (XbbException e) {
            log.error("com.xbongbong.paas.service.log.operation.impl.CustomerOperationLogHandleImpl.update", e);
        }
    }


    @Override
    @Async("sysLogThreadPool")
    public void add(AddFocusDTO addFocusDTO) {
        addFocus(addFocusDTO);
    }

    @Override
    @Async("sysLogThreadPool")
    public void delete(DeleteFocusDTO deleteFocusDTO) {
        deleteFocus( deleteFocusDTO);
    }

    @Override
    @Async("sysLogThreadPool")
    public void backToPublic(BackToPublicDTO backToPublicDTO) {
        try {
            ListBatchDTO listBatchDTO = backToPublicDTO.getListBatchDTO();
            String corpid = listBatchDTO.getCorpid();
            String userId = listBatchDTO.getUserId();
            String loginUserName = listBatchDTO.getLoginUserName();
            List<String> customerNameList = backToPublicDTO.getCustomerNameList();
            List<PaasFormDataEntityExt> dataList = backToPublicDTO.getDataList();
            Integer isBatch = backToPublicDTO.getIsBatch();
            //退回公海池日志
            String logMemo = StringUtils.join(customerNameList, "、");
            if (Objects.equals(1,isBatch)) {
                String memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_USER_BATCH_BACK_CUSTOMER), loginUserName, dataList.size());
                List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                InfoArrPojo infoArrPojo = new InfoArrPojo();
                infoArrPojo.setTitle(OperationLogHelp.setDetailTitle());
                infoArrPojo.setContent(logMemo);
                infoArrPojoList.add(infoArrPojo);
                mongoLogHelp.buildLog4InfoArrWithoutAsync(infoArrPojoList, corpid, userId, loginUserName, OperateModuleTypeEnum.CUSTOMER, OperateTypeEnum.RETURN_TO_PUBLIC,
                        "", "", memo, listBatchDTO.getHttpHeader());
            }else{
                if(CollectionsUtil.isEmpty(dataList)){
                    return;
                }
                String paasFormName = getPaasFormName(corpid, dataList.get(0).getFormId(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                String memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_USER_BACK_CUSTOMER), loginUserName, paasFormName, logMemo);
                mongoLogHelp.buildLogWithoutAsync(corpid, userId, loginUserName, OperateModuleTypeEnum.CUSTOMER, OperateTypeEnum.RETURN_TO_PUBLIC,
                        dataList.get(0).getDataId().toString(), logMemo, memo, listBatchDTO.getHttpHeader());
            }
        }catch (XbbException e){
            log.error("com.xbongbong.paas.service.log.crm.operation.impl.CustomerOperationLogHandleImpl.backToPublic",e);
        }
    }

    @Override
    @Async("sysLogThreadPool")
    public void merge(CustomerMergeLogDTO customerMergeLogDTO) {
        try {
            CustomerMergeDTO customerMergeDTO = customerMergeLogDTO.getCustomerMergeDTO();
            String corpid = customerMergeDTO.getCorpid();
            String userId = customerMergeDTO.getUserId();
            String userName = customerMergeDTO.getLoginUserName();
            CustomerEntityExt beforeUpdateCustomer = customerMergeLogDTO.getBeforeUpdateCustomer();
            CustomerEntityExt afterUpdateEntity = customerMergeLogDTO.getAfterUpdateEntity();
            CustomerEntityExt delEntity = customerMergeLogDTO.getDelEntity();
            String paasFormName = getPaasFormName(corpid, beforeUpdateCustomer.getFormId(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
            String updateName = OperationLogHelp.getName(type(),beforeUpdateCustomer.getData());
            String delName = OperationLogHelp.getName(type(),delEntity.getData());
            String memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_CUSTOMER_MERGE), userName,paasFormName,delName,updateName );
            PaasFormExplainEntity explainEntity = proFormHelp.getExplainEntity(corpid, beforeUpdateCustomer.getFormId(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
            Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(explainEntity.getExplains(), null);
            // 用了处理日志中的子表单数据
            if (Objects.nonNull(afterUpdateEntity.getSubFormData())) {
                afterUpdateEntity.getData().putAll(afterUpdateEntity.getSubFormData());
            }
            if (Objects.nonNull(beforeUpdateCustomer.getSubFormData())) {
                beforeUpdateCustomer.getData().putAll(beforeUpdateCustomer.getSubFormData());
            }

            JSONObject newObj = JsonHelperUtil.parseObject(JSONObject.toJSONString(afterUpdateEntity));
            JSONObject oldObj = JsonHelperUtil.parseObject(JSONObject.toJSONString(beforeUpdateCustomer));
            List<DetailLogPojo> detailArr = logHelp.getDetailArr4Data(corpid, RedundantTemplateTypeEnum.CUSTOMER,
                    explainMap, oldObj, newObj);
            mongoLogHelp.buildLog4DetailArr(detailArr, corpid, userId, userName, OperateModuleTypeEnum.CUSTOMER, OperateTypeEnum.CUSTOMER_MERGE,
                    beforeUpdateCustomer.getDataId().toString(), updateName, memo, customerMergeDTO.getHttpHeader());
        }catch (XbbException e){
            log.error("com.xbongbong.paas.service.log.crm.operation.impl.CustomerOperationLogHandleImpl.merge",e);
        }
    }

    @Override
    @Async("sysLogThreadPool")
    public void thoroughDelete(ThoroughDeleteLogDTO thoroughDeleteLogDTO) {
        try {
            FormDataThoroughDeleteDTO formDataThoroughDeleteDTO = thoroughDeleteLogDTO.getFormDataThoroughDeleteDTO();
            String corpid = formDataThoroughDeleteDTO.getCorpid();
            String userId = formDataThoroughDeleteDTO.getUserId();
            String userName = formDataThoroughDeleteDTO.getLoginUserName();
            List<Long> dataIdList = formDataThoroughDeleteDTO.getDataIdList();
            Long formId = formDataThoroughDeleteDTO.getFormId();
            String nameStr = thoroughDeleteLogDTO.getNameStr();
            String paasFormName = getPaasFormName(corpid, formId, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
            String memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_USER_BATCH_COMPLETELY_DELETE_FORM_DETAIL),
                    userName,paasFormName, dataIdList.size());
            List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            InfoArrPojo infoArrPojo = new InfoArrPojo();
            infoArrPojo.setTitle(OperationLogHelp.setDetailTitle());
            infoArrPojo.setContent(nameStr);
            infoArrPojoList.add(infoArrPojo);
            mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, userName, OperateModuleTypeEnum.CUSTOMER, OperateTypeEnum.COMPLETELY_DELETE,
                    "", "", memo, formDataThoroughDeleteDTO.getHttpHeader());
        }catch (XbbException e){
            log.error("com.xbongbong.paas.service.log.crm.operation.impl.CustomerOperationLogHandleImpl.thoroughDelete",e);
        }
    }

    @Override
    @Async("sysLogThreadPool")
    public void revert(RevertLogDTO revertLogDTO) {
        try {
            ListBatchDTO listBatchDTO = revertLogDTO.getListBatchDTO();
            String userId = listBatchDTO.getUserId();
            String corpid = listBatchDTO.getCorpid();
            String userName = listBatchDTO.getLoginUserName();
            List<Long> dataIdList = listBatchDTO.getDataIdList();
            Long formId = listBatchDTO.getFormId();
            Integer businessType = listBatchDTO.getBusinessType();
            String nameStr = revertLogDTO.getNameStr();
            String paasFormName = getPaasFormName(corpid, formId, businessType);
            String memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_USER_BATCH_REVERT_FORM_DETAIL), userName
                    ,paasFormName, dataIdList.size());
            List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            InfoArrPojo infoArrPojo = new InfoArrPojo();
            infoArrPojo.setTitle(OperationLogHelp.setDetailTitle());
            infoArrPojo.setContent(nameStr);
            infoArrPojoList.add(infoArrPojo);
            mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, userName, OperateModuleTypeEnum.CUSTOMER, OperateTypeEnum.REVERT_CANCEL,
                    "", "", memo, listBatchDTO.getHttpHeader());
        }catch (XbbException e){
            log.error("com.xbongbong.paas.service.log.crm.operation.impl.CustomerOperationLogHandleImpl.revert",e);
        }
    }

    @Override
    @Async("sysLogThreadPool")
    public void grab(CustomerGrabLogDTO customerGrabLogDTO) {
        try {
            ListBatchDTO listBatchDTO = customerGrabLogDTO.getListBatchDTO();
            Integer isBatch = listBatchDTO.getIsBatch();
            String logMemo = customerGrabLogDTO.getLogMemo();
            String corpid = listBatchDTO.getCorpid();
            String userId = listBatchDTO.getUserId();
            String userName = listBatchDTO.getLoginUserName();
            Long formId = listBatchDTO.getFormId();
            Integer businessType = listBatchDTO.getBusinessType();
            List<Long> dataIdList = listBatchDTO.getDataIdList();
            String paasFormName = getPaasFormName(corpid, formId, businessType);
            if (Objects.equals(1,isBatch)) {
                String memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_USER_BATCH_GRAB_CUSTOMER), userName,
                        paasFormName, dataIdList.size());
                List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                InfoArrPojo infoArrPojo = new InfoArrPojo();
                infoArrPojo.setTitle(OperationLogHelp.setDetailTitle());
                infoArrPojo.setContent(logMemo);
                infoArrPojoList.add(infoArrPojo);
                mongoLogHelp.buildLog4InfoArrWithoutAsync(infoArrPojoList, corpid, userId, userName, OperateModuleTypeEnum.CUSTOMER, OperateTypeEnum.SNATCH_CUSTOMER_FROM_PUBLIC,
                        "", "", memo, listBatchDTO.getHttpHeader());
            }else{
                Boolean fromCheckRepeatForm = listBatchDTO.getFromCheckRepeatForm();
                String memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_USER_GRAB_CUSTOMER), userName, paasFormName, logMemo);
                if(fromCheckRepeatForm){
                    memo = String.format(I18nMessageUtil.getMessage(CrmLogMemoConstant.LOG_MEMO_USER_GRAB_FROM_CHECKREPEAT), userName, paasFormName, logMemo);
                }
                mongoLogHelp.buildLogWithoutAsync(corpid, userId, userName, OperateModuleTypeEnum.CUSTOMER, OperateTypeEnum.SNATCH_CUSTOMER_FROM_PUBLIC,
                        dataIdList.get(0).toString(), logMemo, memo, listBatchDTO.getHttpHeader());
            }
        }catch (XbbException e){
            log.error("com.xbongbong.paas.service.log.crm.operation.impl.CustomerOperationLogHandleImpl.grab",e);
        }
    }
}
